package com.unitd.base.module.master.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.unitd.base.frame.plugin.module.dto.ResponseUtils;
import com.unitd.base.frame.util.BeanUtils;
import com.unitd.base.frame.util.ListUtils;
import com.unitd.base.module.comm.enums.DeleteFlagEnum;
import com.unitd.base.module.comm.enums.StatusEnum;
import com.unitd.base.module.consumer.comm.enums.UserLevelEnum;
import com.unitd.base.module.master.mybatis.mapper.CompanyDatasourceMapper;
import com.unitd.base.module.master.mybatis.mapper.CompanyMapper;
import com.unitd.base.module.master.mybatis.mapper.CompanyUserMapper;
import com.unitd.base.module.master.mybatis.mapper.UserMapper;
import com.unitd.base.module.master.pojo.dto.CompanyDatasourceVO;
import com.unitd.base.module.master.pojo.dto.UserLevelVO;
import com.unitd.base.module.master.pojo.dto.UserVO;
import com.unitd.base.module.master.pojo.po.*;
import com.unitd.base.module.master.service.SmsLogService;
import com.unitd.base.module.master.service.UserService;
import com.unitd.base.module.shoe.pojo.po.CustomerPO;
import com.unitd.base.module.shoe.service.CustomerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户信息处理的业务逻辑类
 *
 * @author User
 * @version 1.0
 * @filename UserServiceImpl.java
 * @copyright www.pactera.com
 * @date 2020-08-28
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserPO> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private CompanyDatasourceMapper companyDatasourceMapper;
    @Autowired
    private CompanyUserMapper companyUserMapper;
    @Autowired
    private SmsLogService smsLogService;
    @Autowired
    private CustomerService customerService;

    /**
     * 绑定手机
     *
     * @param loginUser  当前登录用户
     * @param jsonParams 请求参数
     * @return 绑定结果
     */
    @Transactional
    @Override
    public Map<String, Object> bindMobile(UserVO loginUser, JSONObject jsonParams) {
        // 手机号码
        String mobile = jsonParams.getString("mobile");
        // 验证码
        String mobileCode = jsonParams.getString("mobile_code");

        SmsLogPO oldSendRecord = smsLogService.getOldSendRecord(mobile);
        if (BeanUtils.isNull(oldSendRecord) || !mobileCode.equals(oldSendRecord.getSmsCode())) {
            return ResponseUtils.toResponsFail("验证码错误");
        }

        // 更新用户手机号信息,绑定手机号码
        UserPO user = userMapper.selectByUserId(loginUser.getUserId());
        user.setMobile(mobile);

        /* 根据手机号码, 去不同渠道信息表中查询是否存在该手机号码,如存在则将该用户绑定到此渠道下 */
        Long datasourceId = null;
        // 1、先查询公司信息表中是否存在该手机号; 存在则进行关联,不存在则继续下一步
        CompanyPO company = companyMapper.selectByAdminPhone(mobile);
        if (!BeanUtils.isNull(company)) {
            user.setUserLevelId(UserLevelEnum.COMPANY_ADMIN.getKey());
            datasourceId = company.getDbId();
        } else {
            // 2、再查询公司用户表中是否存在该手机号; 存在则进行关联,不存在则继续下一步
            CompanyUserPO companyUser = companyUserMapper.selectByUserPhone(mobile);
            if (!BeanUtils.isNull(companyUser)) {
                user.setUserLevelId(companyUser.getUserLevelId());
                datasourceId = companyUser.getCompanyDatasource().getDbId();
            } else {
                // 普通用户
                user.setUserLevelId(UserLevelEnum.ORDINARY_USERS.getKey());

                // 得到所有公司的默认数据源
                List<CompanyDatasourcePO> datasources = companyDatasourceMapper.selectByStatusAndDeleteFlag(StatusEnum.ONE.getCode(), DeleteFlagEnum.NO.getCode());
                if (!ListUtils.isNull(datasources)) {

                    // 轮询不同公司的用户表,判断该用户属于哪几个公司,并往公司用户表插入相应的记录
                    datasources.forEach(e -> {
                        CustomerPO customer = customerService.selectByMobile(e.getDbName(), mobile);
                        if (!BeanUtils.isNull(customer)) {
                            CompanyUserPO companyUserPo = new CompanyUserPO();
                            // 所属公司ID
                            companyUserPo.setCompanyId(e.getCompanyId())
                                    // 用户级别(具体与shop_user_level对应)
                                    .setUserLevelId(UserLevelEnum.ORDINARY_USERS.getKey())
                                    // 公司用户编号
                                    .setUserNo(user.getUserNo())
                                    // 公司用户名称
                                    .setUserName(user.getUserName())
                                    // 公司用户手机号
                                    .setMobile(user.getMobile())
                                    // 公司用户昵称
                                    .setNickName(user.getUserName())
                                    // 数据状态(失效)
                                    .setStatus(StatusEnum.ZERO.getCode());
                            // 保存入库
                            companyUserMapper.insert(companyUserPo);
                        }
                    });
                }
            }
        }

        // 给用户设置默认数据源
        if (datasourceId != null && datasourceId > 0) {
            user.setDefDbId(datasourceId);
        }
        userMapper.updateById(user);

        return ResponseUtils.toResponsSuccess("手机绑定成功");
    }

    /**
     * 根据查询条件获取公司客户分页列表信息
     *
     * @param param 查询条件(包含分页参数)
     * @return 公司用户信息列表
     */
    @Override
    public List<UserVO> listByParam(Map<String, Object> param) {
        List<UserPO> pos = userMapper.listByParam(param);
        return pos.stream().map(this::convertPoToVo).collect(Collectors.toList());
    }

    /**
     * 根据用户ID获取该用户基本信息
     *
     * @param userId 用户ID
     * @return 用户信息
     */
    @Override
    public UserVO selectById(Long userId) {
        UserPO po = userMapper.selectByUserId(userId);
        return convertPoToVo(po);
    }

    /**
     * 修改用户信息
     *
     * @param user 普通用户详情
     * @return 新增/更新结果
     */
    @Override
    public int save(UserVO user, Long dbId) {
        int result = 0;
        UserPO po = convertVoToPo(user);
        po.setDefDbId(dbId);

        result += userMapper.updateById(po);

        return result;
    }

    /**
     * 逻辑删除用户信息
     *
     * @param userId 普通用户ID
     * @return 删除结果
     */
    @Override
    public int deleteById(Long userId) {
        UserPO user = new UserPO();
        user.setId(userId);
        user.setStatus(StatusEnum.ZERO.getCode());
        user.setDeleteFlag(DeleteFlagEnum.YES.getCode());
        return userMapper.updateById(user);
    }

    /**
     * 更改登录用户的默认数据源
     *
     * @param userId 当前登录用户
     * @param dbId   指定的默认数据源ID
     * @return 更改结果
     */
    @Override
    public int setUserDefDatasource(Long userId, Long dbId) {
        UserPO user = userMapper.selectByUserId(userId);
        user.setDefDbId(dbId);
        return userMapper.updateById(user);
    }

    /**
     * 将用户PO对象转换成VO对象
     *
     * @param userPo 用户po对象
     * @return 用户vo对象
     */
    private UserVO convertPoToVo(UserPO userPo) {

        UserVO userVo = new UserVO();
        UserLevelVO userLevel = new UserLevelVO();
        CompanyDatasourceVO datasource = new CompanyDatasourceVO();

        BeanUtils.copyProperties(userPo, userVo);
        if (!BeanUtils.isNull(userPo.getUserLevel())) {
            BeanUtils.copyProperties(userPo.getUserLevel(), userLevel);
        }
        if (!BeanUtils.isNull(userPo.getCompanyDatasource())) {
            BeanUtils.copyProperties(userPo.getCompanyDatasource(), datasource);
        }

        userVo.setCompanyDatasource(datasource);
        userVo.setUserLevel(userLevel);
        userVo.setUserId(userPo.getId());

        return userVo;
    }

    /**
     * 将vo对象转换成po对象
     *
     * @param vo 数据库实体对象
     * @return 数据交互、展示对象
     */
    private UserPO convertVoToPo(UserVO vo) {

        UserPO po = new UserPO();
        BeanUtils.copyProperties(vo, po);
        if (po.getId() == null || po.getId() == 0) {
            po.setId(vo.getUserId());
        }
        return po;
    }
}